package com.yw.service.Impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.yw.mapper.NodeMapper;
import com.yw.service.NodeService;
import com.yw.task.domain.Node;
import com.yw.task.dto.AddNodeDTO;
import com.yw.task.dto.ArrowDTO;
import com.yw.task.dto.AutomaticDTO;
import com.yw.task.dto.NodeInValue;
import com.yw.task.vo.AddNodeVO;
import com.yw.task.vo.AutomaticVO;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class NodeServiceImpl extends ServiceImpl<NodeMapper, Node>
                                implements NodeService {


    @Override
    public AddNodeVO addNode(AddNodeDTO addNodeDTO) {//新增节点
        Node node = new Node();
        switch (addNodeDTO.getNodeType()){
            case "api":
                node.setTaskName(addNodeDTO.getTaskName());
                node.setNodeName(addNodeDTO.getNodeName());
                node.setNodeType(addNodeDTO.getNodeType());
                node.setNodeDesc(addNodeDTO.getNodeDesc());
                node.setInterfaceId(addNodeDTO.getInterfaceId());
                node.setNodeInValues(JSONUtil.toJsonStr(addNodeDTO.getNodeInValues()));
                node.setUpstreamIds(JSONUtil.toJsonStr(addNodeDTO.getUpstreamIds()));
                node.setDownstreamIds(JSONUtil.toJsonStr(addNodeDTO.getDownstreamIds()));
                node.setCacheRule(addNodeDTO.getCacheRule());
                node.setDay(addNodeDTO.getDay());
                node.setHour(addNodeDTO.getHour());
                node.setMin(addNodeDTO.getMin());
                node.setCodeId(addNodeDTO.getCodeId());
                node.setRetryMechanisms(JSONUtil.toJsonStr(addNodeDTO.getRetryMechanisms()));
                this.save(node);
                break;
            case "py":
                node.setTaskName(addNodeDTO.getTaskName());
                node.setNodeName(addNodeDTO.getNodeName());
                node.setNodeType(addNodeDTO.getNodeType());
                node.setNodeDesc(addNodeDTO.getNodeDesc());
                node.setNodeInValues(JSONUtil.toJsonStr(addNodeDTO.getNodeInValues()));
                node.setUpstreamIds(JSONUtil.toJsonStr(addNodeDTO.getUpstreamIds()));
                node.setDownstreamIds(JSONUtil.toJsonStr(addNodeDTO.getDownstreamIds()));
                node.setPyId(addNodeDTO.getPyId());
                break;
            case "out":
                node.setTaskName(addNodeDTO.getTaskName());
                node.setNodeName(addNodeDTO.getNodeName());
                node.setNodeType(addNodeDTO.getNodeType());
                node.setNodeDesc(addNodeDTO.getNodeDesc());
                node.setNodeInValues(JSONUtil.toJsonStr(addNodeDTO.getNodeInValues()));
                node.setUpstreamIds(JSONUtil.toJsonStr(addNodeDTO.getUpstreamIds()));
                node.setDownstreamIds(JSONUtil.toJsonStr(addNodeDTO.getDownstreamIds()));
                node.setDatabaseName(addNodeDTO.getDatabaseName());
                node.setDataTableName(addNodeDTO.getDataTableName());
                break;
            case "clean", "start", "end":
                node.setTaskName(addNodeDTO.getTaskName());
                node.setNodeName(addNodeDTO.getNodeName());
                node.setNodeType(addNodeDTO.getNodeType());
                node.setNodeDesc(addNodeDTO.getNodeDesc());
                node.setNodeInValues(JSONUtil.toJsonStr(addNodeDTO.getNodeInValues()));
                node.setUpstreamIds(JSONUtil.toJsonStr(addNodeDTO.getUpstreamIds()));
                node.setDownstreamIds(JSONUtil.toJsonStr(addNodeDTO.getDownstreamIds()));
                break;
            case "mapping":
                node.setTaskName(addNodeDTO.getTaskName());
                node.setNodeName(addNodeDTO.getNodeName());
                node.setNodeType(addNodeDTO.getNodeType());
                node.setNodeDesc(addNodeDTO.getNodeDesc());
                node.setNodeInValues(JSONUtil.toJsonStr(addNodeDTO.getNodeInValues()));
                node.setUpstreamIds(JSONUtil.toJsonStr(addNodeDTO.getUpstreamIds()));
                node.setDownstreamIds(JSONUtil.toJsonStr(addNodeDTO.getDownstreamIds()));
                node.setAssetId(addNodeDTO.getAssetId());
                break;
        }
        if (this.save(node)){
            AddNodeVO addNodeVO = new AddNodeVO();
            addNodeVO.setNodeId(node.getId());
            addNodeVO.setNodeName(node.getNodeName());
            return addNodeVO;
        }else {
            return null;
        }
    }//新增节点

    //自动解析
    @Override
    public List<AutomaticVO> automatic(AutomaticDTO automaticDTO) {
        LambdaQueryWrapper<Node> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Node::getTaskName,automaticDTO.getTaskName());
        List<Node> nodes = this.list(wrapper);
        ArrayList<AutomaticVO> automaticVOS = new ArrayList<>();
        for (Node node : nodes) {
            Gson gson = new Gson();
            List<Integer> list = gson.fromJson(node.getUpstreamIds(), new TypeToken<List<Integer>>() {}.getType());//找上游节点包含start
            if (list.contains(1)){//start节点id为1
                List<NodeInValue> values= gson.fromJson(node.getNodeInValues(), new TypeToken<List<NodeInValue>>() {
                }.getType());//说明上游节点有start，此时把其中的输入参数提出来
                for (NodeInValue nodeInValue : values) {
                    AutomaticVO automaticVO = new AutomaticVO();
                    automaticVO.setIsEable(0);
                    automaticVO.setDownStreamName(node.getNodeName());
                    for (String valueName : automaticDTO.getValueNames()) {
                        automaticVO.setValueName(valueName);
                        if (nodeInValue.getUpstream().equals(valueName)){
                          automaticVO.setDownStreamValue(nodeInValue.getValueName());
                          break;
                        }
                    }
                    automaticVOS.add(automaticVO);
                }
            }
        }
        return automaticVOS;
    }

    //箭头对应的接口
    @Override
    public Boolean UpAndDownIdAssignment(ArrowDTO arrowDTO) {
        //得到上下游的节点对象
        Node upOne = this.getById(arrowDTO.getUpstreamId());
        Node downOne = this.getById(arrowDTO.getDownstreamId());
        //将下游节点的id赋值给上游节点的下游节点字段
        try {
            List<Integer> downIds = new ObjectMapper().readValue(upOne.getDownstreamIds(), new TypeReference<List<Integer>>() {});
            downIds.add(downOne.getId());
            upOne.setDownstreamIds(JSONUtil.toJsonStr(downIds));
            //同理
            List<Integer> upIds = new ObjectMapper().readValue(downOne.getUpstreamIds(), new TypeReference<List<Integer>>() {});
            upIds.add(upOne.getId());
            downOne.setUpstreamIds(JSONUtil.toJsonStr(upIds));
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        ArrayList<Node> nodes = new ArrayList<>();
        nodes.add(upOne);
        nodes.add(downOne);
        //更新到数据库
        if (this.updateBatchById(nodes)){
            return true;
        }else {
            return false;
        }

    }
}
